package sk.hackcraft.util.agent_simulation;

import sk.hackcraft.util.agent_simulation.agent.Agent;
import sk.hackcraft.util.agent_simulation.messaging.Message;
import java.util.PriorityQueue;

public abstract class AgentSimulation
{
	private PriorityQueue<Message> messageBox;
	private double currentTime;
	
	private Agent bossAgent;
	private SimulationController controller;
	
	private long replicationCount;
	
	public AgentSimulation(long replicationCount)
	{
		this.currentTime = 0;
		this.messageBox = new PriorityQueue<Message>();
		
		this.replicationCount = replicationCount;
	}
	
	public void setController(SimulationController controller)
	{
		this.controller = controller;
	}
	
	public void sendMessage(Message message)
	{
		messageBox.add(message);
	}

	protected Agent getBossAgent()
	{
		return bossAgent;
	}

	protected void setBossAgent(Agent bossAgent)
	{
		this.bossAgent = bossAgent;
	}

	public double getCurrentTime()
	{
		return currentTime;
	}
	
	private void runReplication()
	{
		messageBox.clear();
		
		beforeRunAction();
		
		while(!messageBox.isEmpty())
		{
			Message message = messageBox.poll();
			
			if(message.hasAddressee())
			{
				message.getAddressee().processMessage(message);
			}
			else
			{
				bossAgent.getManager().processMessage(message);
			}
		}
		
		afterRunAction();
	}
	
	public void simulate()
	{
		beforeSimulationAction();
		
		for(long replicationId=1; replicationId <= replicationCount; replicationId++)
		{
			runReplication();
			
			if(controller != null)
			{
				controller.setProgress((int) (replicationId / replicationCount * 100));
			}
		}
		
		afterSimulationAction();
	}

	protected abstract void beforeRunAction();

	protected abstract void afterRunAction();
	
	private void beforeSimulationAction()
	{
		getBossAgent().getManager().updateMessageCodeStructure();
	}
	
	private void afterSimulationAction()
	{
		
	}
}
